package fr.univ.lille1.android;

import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
import android.text.Html;
import android.text.TextUtils;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.actionbarsherlock.app.SherlockActivity;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.plus.PlusClient;
import com.google.android.gms.plus.model.people.Person;
import com.googlecode.androidannotations.annotations.AfterViews;
import com.googlecode.androidannotations.annotations.Background;
import com.googlecode.androidannotations.annotations.Click;
import com.googlecode.androidannotations.annotations.EActivity;
import com.googlecode.androidannotations.annotations.UiThread;
import com.googlecode.androidannotations.annotations.ViewById;
import com.googlecode.androidannotations.annotations.res.HtmlRes;
import com.googlecode.androidannotations.annotations.res.StringRes;

import fr.univ.lille1.android.domain.User;

@EActivity(R.layout.activity_main)
public class LogInActivity extends SherlockActivity {
	private static final int REQUEST_CODE_SIGN_IN = 42;

	// Authentication.
	private PlusClient mPlusClient;
	private ConnectionResult mConnectionResult;

	// Gui.
	@ViewById(R.id.buttonGoogleSignIn)
	SignInButton mButtonGoogleSignIn;
	@ViewById(R.id.textViewWelcome)
	TextView mTextViewWelcome;
	@ViewById(R.id.editTextEmail)
	EditText mEditTextEmail;
	@ViewById(R.id.editTextPassword)
	EditText mEditTextPassword;
	@ViewById(R.id.buttonTagThisSignIn)
	Button mButtonTagThisSignIn;

	// Resources.
	@HtmlRes(R.string.text_welcome)
	CharSequence mTextWelcome;
	@StringRes(R.string.app_name)
	String mAppName;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
		// If the user is already connected with Google Plus, we launch the next
		// activity.
		mPlusClient = new PlusClient.Builder(this,
				mGooglePlusConnectionCallbacks,
				mGooglePlusOnConnectionFailedListener).setVisibleActivities(
				"http://schemas.google.com/AddActivity",
				"http://schemas.google.com/BuyActivity").build();

		if (mPlusClient.isConnected()) {
			startNextActivity();
		}
	}

	@AfterViews
	void afterView() {
		final String textWelcome = String.format(mTextWelcome.toString(),
				mAppName);
		mTextViewWelcome.setText(Html.fromHtml(textWelcome));
	}

	@Override
	public void onStart() {
		super.onStart();
		mPlusClient.connect();
	}

	@Override
	public void onStop() {
		mPlusClient.disconnect();
		super.onStop();
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == REQUEST_CODE_SIGN_IN) {
			if (resultCode == RESULT_OK
					&& (!mPlusClient.isConnected() && !mPlusClient
							.isConnecting())) {
				mConnectionResult = null;
				// This time, connect should succeed.
				mPlusClient.connect();
			}
		}
	}

	@Click(R.id.buttonGoogleSignIn)
	void googlePlusSignInClick() {
		try {
			if (mConnectionResult != null) {
				mConnectionResult.startResolutionForResult(LogInActivity.this,
						REQUEST_CODE_SIGN_IN);
			} else {
				Toast.makeText(this, R.string.error_message_already_connected,
						Toast.LENGTH_SHORT).show();
			}
		} catch (SendIntentException e) {
			mPlusClient.connect();
		}
	}

	@Click(R.id.buttonTagThisSignIn)
	void tagThisSignInClick() {
		tryConnect();
	}

	/**
	 * Try to connect with the tag this form.
	 */
	public void tryConnect() {
		mButtonGoogleSignIn.setEnabled(false);
		mButtonTagThisSignIn.setEnabled(false);
		mEditTextEmail.setError(null);
		mEditTextPassword.setError(null);

		boolean cancel = false;
		View focusView = null;

		final String username = mEditTextEmail.getText().toString();
		final String password = mEditTextPassword.getText().toString();

		// User must fill all fields.
		if (TextUtils.isEmpty(username)) {
			mEditTextEmail.setError(getString(R.string.error_message_no_value));
			cancel = true;
			focusView = mEditTextEmail;
		} else if (TextUtils.isEmpty(password)) {
			mEditTextPassword
					.setError(getString(R.string.error_message_no_value));
			cancel = true;
			focusView = mEditTextPassword;
		}
		// If there is one field empty, we indicate at the user. Otherwise, we
		// launch the connection request.
		if (cancel) {
			focusView.requestFocus();
			mButtonGoogleSignIn.setEnabled(true);
			mButtonTagThisSignIn.setEnabled(true);
		} else {
			setProgressBarIndeterminateVisibility(true);
			authenticationTagThisBackground();
		}
	}

	@Background
	void authenticationTagThisBackground() {
		// TODO Request on the tag this server for authentication.
		authenticationTagThisResult();
	}

	@UiThread
	void authenticationTagThisResult() {
		setProgressBarIndeterminateVisibility(false);
		mButtonGoogleSignIn.setEnabled(true);
		mButtonTagThisSignIn.setEnabled(true);
		startNextActivity();
	}

	/**
	 * Start the next activity when the user is connected.
	 */
	private void startNextActivity() {
		CommentActivity_.intent(this).start();
		finish();
	}

	private final ConnectionCallbacks mGooglePlusConnectionCallbacks = new ConnectionCallbacks() {

		public void onDisconnected() {
			// User is disconnected.
		}

		public void onConnected(Bundle connectionHint) {
			final Person person = mPlusClient.getCurrentPerson();
			final String name = person.getDisplayName();
			final String accountName = mPlusClient.getAccountName();
			final User user = new User(0, name, "", accountName);
			Toast.makeText(LogInActivity.this, "Welcome " + user.getName(),
					Toast.LENGTH_LONG).show();
			startNextActivity();
		}
	};

	private final OnConnectionFailedListener mGooglePlusOnConnectionFailedListener = new OnConnectionFailedListener() {

		public void onConnectionFailed(ConnectionResult result) {
			mConnectionResult = result;
		}
	};
}
